/*!
    \file    link32fa016bx_rcu.h
    \brief   definitions for the RCU

    \version 2023-10-5, V1.0.0, firmware for LINK32FA016BX
*/

/*
    Copyright (c) 2024, LinkLiao(linkliao610@163.com)

*/
#ifndef LINK32FA016BX_RCU_H
#define LINK32FA016BX_RCU_H

#include "link32fa016bx.h"

LINK32FA016BX_BEGIN_DECLS

/* RCU definitions */
#define RCU                             RCU_BASE

/* registers definitions */

#define RCU_CTL                         REG32(RCU + 0x00U)        /*!< control register */
#define RCU_CFG0                        REG32(RCU + 0x04U)        /*!< clock configuration register 0 */
#define RCU_APBRST                      REG32(RCU + 0x10U)        /*!< APB reset register */
#define RCU_AHBRST                      REG32(RCU + 0x14U)        /*!< AHB reset register */
#define RCU_APBCLKON                    REG32(RCU + 0x18U)        /*!< APB enable register */
#define RCU_AHBCLKON                    REG32(RCU + 0x1CU)        /*!< AHB enable register */
#define RCU_BDCTL                       REG32(RCU + 0x20U)        /*!< backup domain control register */
#define RCU_CSR                         REG32(RCU + 0x24U)        /*!< Control and status register   */
#define RCU_CFG1                        REG32(RCU + 0x2CU)        /*!< clock configuration register 1 */


/* bits definitions */
/* RCU_CTL */
#define RCU_CTL_HSI_ON                  BIT(0)                    /*!< internal high speed oscillator enable */
#define RCU_CTL_HSI_RDY                 BIT(1)                    /*!< IRC8M high speed internal oscillator ready flag */
#define RCU_CTL_HSI_TRIM                BITS(3,7)                 /*!< high speed internal oscillator clock trim adjust value */
#define RCU_CTL_HSI_CAL                 BITS(8,15)                /*!< high speed internal oscillator calibration value register */
#define RCU_CTL_HSE_ON                  BIT(16)                   /*!< external high speed oscillator enable */
#define RCU_CTL_HSE_RDY                 BIT(17)                   /*!< external crystal oscillator clock ready flag */
#define RCU_CTL_HSE_BYP                 BIT(18)                   /*!< external crystal oscillator clock bypass mode enable */
#define RCU_CTL_CSS_ON                  BIT(19)                   /*!< HXTAL clock monitor enable */
#define RCU_CTL_PLL_ON                  BIT(24)                   /*!< PLL enable */
#define RCU_CTL_PLL_RDY                 BIT(25)                   /*!< PLL clock ready flag */


#define RCU_CFG0_SW                     BITS(0,1)                 /*!< root clock switch */
#define RCU_CFG0_SWS                    BITS(2,3)                 /*!< root clock switch status */
#define RCU_CFG0_HPRE                   BITS(4,7)                 /*!< AHB prescaler selection */
#define RCU_CFG0_PPRE                   BITS(8,10)                /*!< APB1 prescaler selection */
#define RCU_CFG0_PLL_SRC                BIT(16)                   /*!< PLL clock source selection */
#define RCU_CFG0_PLL_MUL                BITS(18,21)               /*!< PLL clock multiplication factor */
#define RCU_CFG0_MCO                    BITS(24,27)               /*!< CKOUT0 clock source selection */

/* RCU_APBRST */
#define RCU_APBRST_SYSCFG               BIT(0)                    /*!< SysCfg reset */
#define RCU_APBRST_PMU                  BIT(1)                    /*!< PMU reset */
#define RCU_APBRST_RTC                  BIT(2)                    /*!< RTC reset */
#define RCU_APBRST_WWDG                 BIT(3)                    /*!< WWDG reset */
#define RCU_APBRST_IWDG                 BIT(4)                    /*!< IWDG reset */
#define RCU_APBRST_PWM0                 BIT(5)                    /*!< PWM0 reset */
#define RCU_APBRST_PWM1                 BIT(6)                    /*!< PWM1 reset */
#define RCU_APBRST_SPIH0                BIT(7)                    /*!< SPIH0 reset */
#define RCU_APBRST_SPIH1                BIT(8)                    /*!< SPIH1 reset */
#define RCU_APBRST_I2C0                 BIT(9)                    /*!< I2C0 reset */
#define RCU_APBRST_I2C1                 BIT(10)                   /*!< I2C1 reset */
#define RCU_APBRST_UART0                BIT(11)                   /*!< UART0 reset */
#define RCU_APBRST_UART1                BIT(12)                   /*!< UART1 reset */
#define RCU_APBRST_SPID0                BIT(13)                   /*!< SPID0 reset */
#define RCU_APBRST_SPID1                BIT(14)                   /*!< SPID1 reset */
#define RCU_APBRST_DMA                  BIT(15)                   /*!< DMA reset */
#define RCU_APBRST_ADC0                 BIT(16)                   /*!< ADC0 reset */
#define RCU_APBRST_ADC1                 BIT(17)                   /*!< ADC1 reset */
#define RCU_APBRST_ADC2                 BIT(18)                   /*!< ADC2 reset */
#define RCU_APBRST_ADC3                 BIT(19)                   /*!< ADC3 reset */
#define RCU_APBRST_ADC4                 BIT(20)                   /*!< ADC4 reset */
#define RCU_APBRST_ADC5                 BIT(21)                   /*!< ADC5 reset */
#define RCU_APBRST_ADC6                 BIT(22)                   /*!< ADC6 reset */
#define RCU_APBRST_ADC7                 BIT(23)                   /*!< ADC7 reset */

/* RCU_AHBRST */
#define RCU_AHBRST_GPIO0                BIT(0)                    /*!< GPIO0 reset */
#define RCU_AHBRST_GPIO1                BIT(1)                    /*!< GPIO1 reset */
#define RCU_AHBRST_GPIO2                BIT(2)                    /*!< GPIO2 reset */
#define RCU_AHBRST_GPIO3                BIT(3)                    /*!< GPIO3 reset */
#define RCU_AHBRST_SDIO                 BIT(5)                    /*!< SDIO reset */
#define RCU_AHBRST_USB                  BIT(6)                    /*!< USB reset */
#define RCU_AHBRST_CRC                  BIT(7)                    /*!< CRC reset */
#define RCU_AHBRST_FMC                  BIT(9)                    /*!< FMC reset */

#define RCU_AHBRST_DEBUG                BIT(16)                   /*!< DEBUG reset */
#define RCU_AHBRST_CLINT                BIT(17)                   /*!< CLINT reset */
#define RCU_AHBRST_PLIC                 BIT(18)                   /*!< PLIC reset */
#define RCU_AHBRST_UARTX                BIT(19)                   /*!< UARTX reset */

/* RCU_APBCLKON */
#define RCU_APBCLKON_SYSCFG             BIT(0)                    /*!< SysCfg clock on */
#define RCU_APBCLKON_PMU                BIT(1)                    /*!< PMU clock on */
#define RCU_APBCLKON_RTC                BIT(2)                    /*!< RTC clock on */
#define RCU_APBCLKON_WWDG               BIT(3)                    /*!< WWDG clock on */
#define RCU_APBCLKON_IWDG               BIT(4)                    /*!< IWDG clock on */
#define RCU_APBCLKON_PWM0               BIT(5)                    /*!< PWM0 clock on */
#define RCU_APBCLKON_PWM1               BIT(6)                    /*!< PWM1 clock on */
#define RCU_APBCLKON_SPIH0              BIT(7)                    /*!< SPIH0 clock on */
#define RCU_APBCLKON_SPIH1              BIT(8)                    /*!< SPIH1 clock on */
#define RCU_APBCLKON_I2C0               BIT(9)                    /*!< I2C0 clock on */
#define RCU_APBCLKON_I2C1               BIT(10)                   /*!< I2C1 clock on */
#define RCU_APBCLKON_UART0              BIT(11)                   /*!< UART0 clock on */
#define RCU_APBCLKON_UART1              BIT(12)                   /*!< UART1 clock on */
#define RCU_APBCLKON_SPID0              BIT(13)                   /*!< SPID0 clock on */
#define RCU_APBCLKON_SPID1              BIT(14)                   /*!< SPID1 clock on */
#define RCU_APBCLKON_DMA                BIT(15)                   /*!< DMA clock on */
#define RCU_APBCLKON_ADC0               BIT(16)                   /*!< ADC0 clock on */
#define RCU_APBCLKON_ADC1               BIT(17)                   /*!< ADC1 clock on */
#define RCU_APBCLKON_ADC2               BIT(18)                   /*!< ADC2 clock on */
#define RCU_APBCLKON_ADC3               BIT(19)                   /*!< ADC3 clock on */
#define RCU_APBCLKON_ADC4               BIT(20)                   /*!< ADC4 clock on */
#define RCU_APBCLKON_ADC5               BIT(21)                   /*!< ADC5 clock on */
#define RCU_APBCLKON_ADC6               BIT(22)                   /*!< ADC6 clock on */
#define RCU_APBCLKON_ADC7               BIT(23)                   /*!< ADC7 clock on */

/* RCU_AHBCLKON */
#define RCU_AHBCLKON_GPIO0              BIT(0)                    /*!< GPIO0 clock on */
#define RCU_AHBCLKON_GPIO1              BIT(1)                    /*!< GPIO1 clock on */
#define RCU_AHBCLKON_GPIO2              BIT(2)                    /*!< GPIO2 clock on */
#define RCU_AHBCLKON_GPIO3              BIT(3)                    /*!< GPIO3 clock on */
#define RCU_AHBCLKON_SDIO               BIT(5)                    /*!< SDIO clock on */
#define RCU_AHBCLKON_USB                BIT(6)                    /*!< USB clock on */
#define RCU_AHBCLKON_CRC                BIT(7)                    /*!< CRC clock on */
#define RCU_AHBCLKON_FMC                BIT(9)                    /*!< FMC clock on */

#define RCU_AHBCLKON_DEBUG              BIT(16)                   /*!< DEBUG clock on */
#define RCU_AHBCLKON_CLINT              BIT(17)                   /*!< CLINT clock on */
#define RCU_AHBCLKON_PLIC               BIT(18)                   /*!< PLIC clock on */
#define RCU_AHBCLKON_UARTX              BIT(19)                   /*!< UARTX clock on */


/* RCU_BDCTL */
#define RCU_BDCTL_LSE_ON                BIT(0)                    /*!< low speed crystal oscillator enable */
#define RCU_BDCTL_LSE_RDY               BIT(1)                    /*!< low speed crystal oscillator ready flag */
#define RCU_BDCTL_LSE_BYP               BIT(2)                    /*!< low speed crystal oscillator bypass mode enable */
#define RCU_BDCTL_RTC_SEL               BITS(8,9)                 /*!< RTC clock entry selection */
#define RCU_BDCTL_RTC_EN                BIT(15)                   /*!< RTC clock enable */
#define RCU_BDCTL_BD_RST                BIT(16)                   /*!< backup domain reset */

/* RCU_CSR */
#define RCU_RSTSCK_LSI_ON               BIT(0)                    /*!< low speed internal oscillator enable */
#define RCU_RSTSCK_LSI_RDY              BIT(1)                    /*!< low speed internal oscillator ready flag */

/* RCU_CFG1 */
#define RCU_CFG1_PREDIV                 BITS(0,3)                 /*!< PREDV  division factor */


/* constants definitions */
/* define frequence of high speed crystal oscillator in Hz */
#if !defined (HSE_FREQ)
#define HSE_FREQ ((uint32_t)32000000) /*!< value of the external oscillator in Hz */
#endif /* high speed crystal oscillator frequence */

/* define startup timeout value of high speed crystal oscillator (HSE) */
#if !defined  (HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT   ((uint16_t)0xFFFF)
#endif /* high speed crystal oscillator startup timeout */

/* define frequence of internal 8MHz RC oscillator (HSI8M) in Hz */
#if !defined  (HSI8M_FREQ)
#define HSI8M_FREQ  ((uint32_t)8000000)
#endif /* internal 8MHz RC oscillator frequence */

/* define startup timeout value of internal 8MHz RC oscillator (HSI8M) */
#if !defined  (HSI8M_STARTUP_TIMEOUT)
#define HSI8M_STARTUP_TIMEOUT   ((uint16_t)0x0500)
#endif /* internal 8MHz RC oscillator startup timeout */

/* define frequence of internal 40KHz RC oscillator(LSI40K) in Hz */
#if !defined  (LSI40K_FREQ)
#define LSI40K_FREQ  ((uint32_t)4000)
#endif /* internal 40KHz RC oscillator value */

/* define value of low speed crystal oscillator (LSE)in Hz */
#if !defined  (LSE_FREQ)
#define LSE_FREQ  ((uint32_t)32768)
#endif /* low speed crystal oscillator value */

/* define clock source */
#define SW_HSI8M                   ((uint16_t)0U)
#define SW_HSE                     ((uint16_t)1U)
#define SW_PLL                     ((uint16_t)2U)

/* define startup timeout count */
#define PLL_STARTUP_TIMEOUT   ((uint32_t)0xFFFFFU)
#define LSI40K_STARTUP_TIMEOUT       ((uint32_t)0xFFFFFU)
#define LSE_STARTUP_TIMEOUT       ((uint32_t)0x3FFFFFFU)


/* define the peripheral clock enable bit position and its register index offset */
#define RCU_REGIDX_BIT(regidx, bitpos)      (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))
#define RCU_REG_VAL(periph)                 (REG32(RCU + ((uint32_t)(periph) >> 6)))
#define RCU_BIT_POS(val)                    ((uint32_t)(val) & 0x1FU)

/* register offset */
/* peripherals enable */
#define APBCLKON_REG_OFFSET             0x18U                     /*!< APB enable register offset */
#define AHBCLKON_REG_OFFSET             0x1CU                     /*!< AHB enable register offset */

/* peripherals reset */
#define APBRST_REG_OFFSET               0x10U                     /*!< APB reset register offset */
#define AHBRST_REG_OFFSET               0x14U                     /*!< AHB reset register offset */

/* clock control */
#define CTL_REG_OFFSET                  0x00U                     /*!< control register offset */
#define BDCTL_REG_OFFSET                0x20U                     /*!< backup domain control register offset */
#define CSR_REG_OFFSET                  0x24U                     /*!< control and status register offset */

/* configuration register */
#define CFG0_REG_OFFSET                 0x04U                     /*!< clock configuration register 0 offset */
#define CFG1_REG_OFFSET                 0x2CU                     /*!< clock configuration register 1 offset */

/* peripheral clock enable */
typedef enum {
    /* AHB peripherals */
    RCU_CLKON_GPIO0  = RCU_REGIDX_BIT(AHBCLKON_REG_OFFSET, 0U),          /*!<GPIO0 clock */
    RCU_CLKON_GPIO1  = RCU_REGIDX_BIT(AHBCLKON_REG_OFFSET, 1U),          /*!<GPIO1 clock */
    RCU_CLKON_GPIO2  = RCU_REGIDX_BIT(AHBCLKON_REG_OFFSET, 2U),          /*!<GPIO2 clock */
    RCU_CLKON_GPIO3  = RCU_REGIDX_BIT(AHBCLKON_REG_OFFSET, 3U),          /*!<GPIO3 clock */
    RCU_CLKON_SDIO   = RCU_REGIDX_BIT(AHBCLKON_REG_OFFSET, 5U),          /*!<SDIO  clock */
    RCU_CLKON_USB    = RCU_REGIDX_BIT(AHBCLKON_REG_OFFSET, 6U),          /*!<USB   clock */
    RCU_CLKON_CRC    = RCU_REGIDX_BIT(AHBCLKON_REG_OFFSET, 7U),          /*!<CRC   clock */
    RCU_CLKON_FMC    = RCU_REGIDX_BIT(AHBCLKON_REG_OFFSET, 9U),          /*!<FMC   clock */
    RCU_CLKON_DEBUG  = RCU_REGIDX_BIT(AHBCLKON_REG_OFFSET, 16U),         /*!<DEBUG clock */
    RCU_CLKON_CLINT  = RCU_REGIDX_BIT(AHBCLKON_REG_OFFSET, 17U),         /*!<CLINT clock */
    RCU_CLKON_PLIC   = RCU_REGIDX_BIT(AHBCLKON_REG_OFFSET, 18U),         /*!<PLIC  clock */
    RCU_CLKON_UARTX  = RCU_REGIDX_BIT(AHBCLKON_REG_OFFSET, 19U),         /*!<UARTX clock */
    /* APB  peripherals */
    RCU_CLKON_SYSCFG = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 0U),          /*!<SysCfg clock */
    RCU_CLKON_PMU    = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 1U),          /*!<PMU    clock */
    RCU_CLKON_RTC    = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 2U),          /*!<RTC    clock */
    RCU_CLKON_WWDG   = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 3U),          /*!<WWDG   clock */
    RCU_CLKON_IWDG   = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 4U),          /*!<IWDG   clock */
    RCU_CLKON_PWM0   = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 5U),          /*!<PWM0   clock */
    RCU_CLKON_PWM1   = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 6U),          /*!<PWM1   clock */
    RCU_CLKON_SPIH0  = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 7U),          /*!<SPIH0  clock */
    RCU_CLKON_SPIH1  = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 8U),          /*!<SPIH1  clock */
    RCU_CLKON_I2C0   = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 9U),          /*!<I2C0   clock */
    RCU_CLKON_I2C1   = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 10U),         /*!<I2C1   clock */
    RCU_CLKON_UART0  = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 11U),         /*!<UART0  clock */
    RCU_CLKON_UART1  = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 12U),         /*!<UART1  clock */
    RCU_CLKON_SPID0  = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 13U),         /*!<SPID0  clock */
    RCU_CLKON_SPID1  = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 14U),         /*!<SPID1  clock */
    RCU_CLKON_DMA    = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 15U),         /*!<DMA    clock */
    RCU_CLKON_ADC0   = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 16U),         /*!<ADC0   clock */
    RCU_CLKON_ADC1   = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 17U),         /*!<ADC1   clock */
    RCU_CLKON_ADC2   = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 18U),         /*!<ADC2   clock */
    RCU_CLKON_ADC3   = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 19U),         /*!<ADC3   clock */
    RCU_CLKON_ADC4   = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 20U),         /*!<ADC4   clock */
    RCU_CLKON_ADC5   = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 21U),         /*!<ADC5   clock */
    RCU_CLKON_ADC6   = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 22U),         /*!<ADC6   clock */
    RCU_CLKON_ADC7   = RCU_REGIDX_BIT(APBCLKON_REG_OFFSET, 23U),         /*!<ADC7   clock */

} rcu_periph_enum;

/* peripherals reset */
typedef enum {
    /* AHB peripherals */
    RCU_RST_GPIO0    = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 0U),            /*!<GPIO0 reset */
    RCU_RST_GPIO1    = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 1U),            /*!<GPIO1 reset */
    RCU_RST_GPIO2    = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 2U),            /*!<GPIO2 reset */
    RCU_RST_GPIO3    = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 3U),            /*!<GPIO3 reset */
    RCU_RST_SDIO     = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 5U),            /*!<SDIO  reset */
    RCU_RST_USB      = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 6U),            /*!<USB   reset */
    RCU_RST_CRC      = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 7U),            /*!<CRC   reset */
    RCU_RST_FMC      = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 9U),            /*!<FMC   reset */
    RCU_RST_DEBUG    = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 16U),           /*!<DEBUG reset */
    RCU_RST_CLINT    = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 17U),           /*!<CLINT reset */
    RCU_RST_PLIC     = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 18U),           /*!<PLIC  reset */
    RCU_RST_UARTX    = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 19U),           /*!<UARTX reset */
    /* APB  peripherals */
    RCU_RST_SYSCFG   = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 0U),            /*!<SysCfg reset */
    RCU_RST_PMU      = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 1U),            /*!<PMU    reset */
    RCU_RST_RTC      = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 2U),            /*!<RTC    reset */
    RCU_RST_WWDG     = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 3U),            /*!<WWDG   reset */
    RCU_RST_IWDG     = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 4U),            /*!<IWDG   reset */
    RCU_RST_PWM0     = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 5U),            /*!<PWM0   reset */
    RCU_RST_PWM1     = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 6U),            /*!<PWM1   reset */
    RCU_RST_SPIH0    = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 7U),            /*!<SPIH0  reset */
    RCU_RST_SPIH1    = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 8U),            /*!<SPIH1  reset */
    RCU_RST_I2C0     = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 9U),            /*!<I2C0   reset */
    RCU_RST_I2C1     = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 10U),           /*!<I2C1   reset */
    RCU_RST_UART0    = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 11U),           /*!<UART0  reset */
    RCU_RST_UART1    = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 12U),           /*!<UART1  reset */
    RCU_RST_SPID0    = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 13U),           /*!<SPID0  reset */
    RCU_RST_SPID1    = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 14U),           /*!<SPID1  reset */
    RCU_RST_DMA      = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 15U),           /*!<DMA    reset */
    RCU_RST_ADC0     = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 16U),           /*!<ADC0   reset */
    RCU_RST_ADC1     = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 17U),           /*!<ADC1   reset */
    RCU_RST_ADC2     = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 18U),           /*!<ADC2   reset */
    RCU_RST_ADC3     = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 19U),           /*!<ADC3   reset */
    RCU_RST_ADC4     = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 20U),           /*!<ADC4   reset */
    RCU_RST_ADC5     = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 21U),           /*!<ADC5   reset */
    RCU_RST_ADC6     = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 22U),           /*!<ADC6   reset */
    RCU_RST_ADC7     = RCU_REGIDX_BIT(APBRST_REG_OFFSET, 23U),           /*!<ADC7   reset */
} rcu_periph_reset_enum;

/* clock stabilization and peripheral reset flags */
typedef enum {
    /* clock stabilization flags */
    RCU_FLAG_HSI8M_RDY  = RCU_REGIDX_BIT(CTL_REG_OFFSET, 1U),       /*!< HSI8M Ready flags */
    RCU_FLAG_HSE_RDY    = RCU_REGIDX_BIT(CTL_REG_OFFSET, 17U),      /*!< HSE Ready flags */
    RCU_FLAG_PLL_RDY    = RCU_REGIDX_BIT(CTL_REG_OFFSET, 25U),      /*!< PLL Ready flags */
    RCU_FLAG_LSE_RDY    = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 1U),     /*!< LSE Ready flags */
    RCU_FLAG_LSI40K_RDY = RCU_REGIDX_BIT(CSR_REG_OFFSET, 1U),    /*!< LSI40K Ready flags */
} rcu_flag_enum;


/* oscillator types */
typedef enum {
    RCU_HSE     = RCU_REGIDX_BIT(CTL_REG_OFFSET, 16U),         /*!< HSE */
    RCU_LSE     = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 0U),        /*!< LSE */
    RCU_HSI8M   = RCU_REGIDX_BIT(CTL_REG_OFFSET, 0U),          /*!< HSI8M */
    RCU_LSI40K  = RCU_REGIDX_BIT(CSR_REG_OFFSET, 0U),          /*!< LSI40K */
    RCU_PLL     = RCU_REGIDX_BIT(CTL_REG_OFFSET, 24U),         /*!< PLL */
} rcu_osci_type_enum;

/* rcu clock frequency */
typedef enum {
    CK_ROOT = 0, /*!< root clock */
    CK_AHB,      /*!< AHB clock */
    CK_APB,      /*!< APB clock */
} rcu_clock_freq_enum;

/* RCU_CFG0 register bit define */
/* root clock source select */
#define CFG0_SW(regval)                 (BITS(0,1) & ((uint32_t)(regval) << 0))
#define RCU_SW_HSI8M                    CFG0_SW(0)                         /*!< root clock source select HSI8M */
#define RCU_SW_HSE                      CFG0_SW(1)                         /*!< root clock source select HSE */
#define RCU_SW_PLL                      CFG0_SW(2)                         /*!< root clock source select PLL */

/* root clock source select status */
#define CFG0_SWS(regval)                (BITS(2,3) & ((uint32_t)(regval) << 2))
#define RCU_SWS_HSI8M                   CFG0_SWS(0)                        /*!< root clock source select HSI8M */
#define RCU_SWS_HSE                     CFG0_SWS(1)                        /*!< root clock source select HSE */
#define RCU_SWS_PLL                     CFG0_SWS(2)                        /*!< root clock source select PLL */

/* AHB prescaler selection */
#define CFG0_HPRE(regval)               (BITS(4,7) & ((uint32_t)(regval) << 4))
#define RCU_AHB_CKROOT_DIV1             CFG0_HPRE(0)                      /*!< AHB prescaler select CK_ROOT */
#define RCU_AHB_CKROOT_DIV2             CFG0_HPRE(8)                      /*!< AHB prescaler select CK_ROOT/2 */
#define RCU_AHB_CKROOT_DIV4             CFG0_HPRE(9)                      /*!< AHB prescaler select CK_ROOT/4 */
#define RCU_AHB_CKROOT_DIV8             CFG0_HPRE(10)                     /*!< AHB prescaler select CK_ROOT/8 */
#define RCU_AHB_CKROOT_DIV16            CFG0_HPRE(11)                     /*!< AHB prescaler select CK_ROOT/16 */
#define RCU_AHB_CKROOT_DIV64            CFG0_HPRE(12)                     /*!< AHB prescaler select CK_ROOT/64 */
#define RCU_AHB_CKROOT_DIV128           CFG0_HPRE(13)                     /*!< AHB prescaler select CK_ROOT/128 */
#define RCU_AHB_CKROOT_DIV256           CFG0_HPRE(14)                     /*!< AHB prescaler select CK_ROOT/256 */
#define RCU_AHB_CKROOT_DIV512           CFG0_HPRE(15)                     /*!< AHB prescaler select CK_ROOT/512 */

/* APB1 prescaler selection */
#define CFG0_PPRE(regval)               (BITS(8,10) & ((uint32_t)(regval) << 8))
#define RCU_APB_CKAHB_DIV1              CFG0_PPRE(0)                     /*< APB1 prescaler select CK_AHB */
#define RCU_APB_CKAHB_DIV2              CFG0_PPRE(4)                     /*< APB1 prescaler select CK_AHB/2 */
#define RCU_APB_CKAHB_DIV4              CFG0_PPRE(5)                     /*< APB1 prescaler select CK_AHB/4 */
#define RCU_APB_CKAHB_DIV8              CFG0_PPRE(6)                     /*< APB1 prescaler select CK_AHB/8 */
#define RCU_APB_CKAHB_DIV16             CFG0_PPRE(7)                     /*< APB1 prescaler select CK_AHB/16 */

/* PLL clock source selection */
#define RCU_PLL_SRC_HSI8M_D2            ((uint32_t)0x00000000U)             /*!< HSI8M/2 clock selected as source clock of PLL */
#define RCU_PLL_SRC_HSE                 RCU_CFG0_PLL_SRC                    /*!< HSE clock selected as source clock of PLL */

/* PLL clock multiplication factor */

#define CFG0_PLL_MUL(regval)              (BITS(18,21) & ((uint32_t)(regval) << 18))
#define RCU_PLL_MUL2                    CFG0_PLL_MUL(0)                       /*!< PLL source clock multiply by 2 */
#define RCU_PLL_MUL3                    CFG0_PLL_MUL(1)                       /*!< PLL source clock multiply by 3 */
#define RCU_PLL_MUL4                    CFG0_PLL_MUL(2)                       /*!< PLL source clock multiply by 4 */
#define RCU_PLL_MUL5                    CFG0_PLL_MUL(3)                       /*!< PLL source clock multiply by 5 */
#define RCU_PLL_MUL6                    CFG0_PLL_MUL(4)                       /*!< PLL source clock multiply by 6 */
#define RCU_PLL_MUL7                    CFG0_PLL_MUL(5)                       /*!< PLL source clock multiply by 7 */
#define RCU_PLL_MUL8                    CFG0_PLL_MUL(6)                       /*!< PLL source clock multiply by 8 */
#define RCU_PLL_MUL9                    CFG0_PLL_MUL(7)                       /*!< PLL source clock multiply by 9 */
#define RCU_PLL_MUL10                   CFG0_PLL_MUL(8)                       /*!< PLL source clock multiply by 10 */
#define RCU_PLL_MUL11                   CFG0_PLL_MUL(9)                       /*!< PLL source clock multiply by 11 */
#define RCU_PLL_MUL12                   CFG0_PLL_MUL(10)                      /*!< PLL source clock multiply by 12 */
#define RCU_PLL_MUL13                   CFG0_PLL_MUL(11)                      /*!< PLL source clock multiply by 13 */
#define RCU_PLL_MUL14                   CFG0_PLL_MUL(12)                      /*!< PLL source clock multiply by 14 */
#define RCU_PLL_MUL15                   CFG0_PLL_MUL(13)                      /*!< PLL source clock multiply by 6.5 */
#define RCU_PLL_MUL16                   CFG0_PLL_MUL(14)                      /*!< PLL source clock multiply by 16 */

/* RTC clock entry selection */
#define BDCTL_RTC_SEL(regval)            (BITS(8,9) & ((uint32_t)(regval) << 8))
#define RCU_RTC_SRC_NONE                 BDCTL_RTC_SEL(0)                     /*!< no clock selected */
#define RCU_RTC_SRC_LSE                  BDCTL_RTC_SEL(1)                     /*!< RTC source clock select LSE    */
#define RCU_RTC_SRC_LSI40K               BDCTL_RTC_SEL(2)                     /*!< RTC source clock select LSI40K */
#define RCU_RTC_SRC_HSE_D32           BDCTL_RTC_SEL(3)                     /*!< RTC source clock select HSE/32 */

/* function declarations */
/* initialization, peripheral clock enable/disable functions */
/* deinitialize the RCU */
void rcu_deinit(void);
/* enable the peripherals clock */
void rcu_periph_clock_enable(rcu_periph_enum periph);
/* disable the peripherals clock */
void rcu_periph_clock_disable(rcu_periph_enum periph);
/* reset the peripherals */
void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset);
/* disable reset the peripheral */
void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset);
/* reset the BKP domain */
void rcu_bkp_reset_enable(void);
/* disable the BKP domain reset */
void rcu_bkp_reset_disable(void);

/* clock configuration functions */
/* configure the root clock source */
void rcu_root_clock_source_config(uint32_t ck_sys);
/* get the root clock source */
uint32_t rcu_root_clock_source_get(void);
/* configure the AHB prescaler selection */
void rcu_ahb_clock_config(uint32_t ck_ahb);
/* configure the APB prescaler selection */
void rcu_apb_clock_config(uint32_t ck_apb1);
/* configure the PLL clock source selection and PLL multiply factor */
void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul);
/* configure the rtc clock source selection*/
void rcu_rtc_clock_config(uint32_t rtc_clock_source);


/* interrupt & flag functions */
/* get the clock ready and periphral reset flags */
FlagStatus rcu_flag_get(rcu_flag_enum flag);
/* clear the reset flag */
void rcu_all_reset_flag_clear(void);
/* get the clock stabilization interrupt and ckm flags */

/* oscillator configuration functions */
/* wait for oscillator stabilization flags is SET or oscillator startup is timeout */
ErrStatus rcu_osci_rdy_wait(rcu_osci_type_enum osci);
/* turn on the oscillator */
void rcu_osci_on(rcu_osci_type_enum osci);
/* turn off the oscillator */
void rcu_osci_off(rcu_osci_type_enum osci);
/* enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */
void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci);
/* disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */
void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci);
/* enable the HXTAL clock monitor */
void rcu_hse_clock_monitor_enable(void);
/* disable the HXTAL clock monitor */
void rcu_hse_clock_monitor_disable(void);

/* set the HSI8M adjust value */
void rcu_hsi8m_trim_set(uint32_t hsi8m_trim);

/* get the root clock, bus and peripheral clock frequency */
uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock);

LINK32FA016BX_END_DECLS

#endif /* LINK32FA016BX_RCU_H */
